package com.yhn.smartalbum.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yhn.smartalbum.enums.BaseErrorCode;
import com.yhn.smartalbum.enums.UserRoleEnum;
import com.yhn.smartalbum.exception.BusinessException;
import com.yhn.smartalbum.exception.ThrowUtils;
import com.yhn.smartalbum.mapper.UserMapper;
import com.yhn.smartalbum.model.dto.common.DeleteRequest;
import com.yhn.smartalbum.model.dto.req.*;
import com.yhn.smartalbum.model.dto.resp.UserLoginRespDTO;
import com.yhn.smartalbum.model.dto.resp.UserRespDTO;
import com.yhn.smartalbum.model.entity.User;
import com.yhn.smartalbum.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.yhn.smartalbum.constant.UserConstant.*;

/**
 * @author 86177
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2024-12-27 16:17:55
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    /**
     * 用户注册
     *
     * @param requestParam 用户注册请求
     * @return 新用户id
     */
    @Override
    public long userRegister(UserRegisterRequestDTO requestParam) {
        String userAccount = requestParam.getUserAccount();
        String userPassword = requestParam.getUserPassword();
        String checkPassword = requestParam.getCheckPassword();
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException("两次输入的密码不一致");
        }
        //参数校验
        //校验账号是否存在
        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUserAccount, userAccount);
        Long count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException("账号已存在");
        }

        //密码加密
        String encryptPassword = getEncryptPassword(userPassword);
        //插入数据
        User user = new User()
                .setUserAccount(userAccount)
                .setUserPassword(encryptPassword)
                .setUserName(DEFAULT_USER_NAME)
                .setUserRole(UserRoleEnum.USER.getValue());
        boolean insert = this.save(user);
        if (!insert) {
            throw new BusinessException("注册失败");
        }
        return user.getId();

    }

    @Override
    public UserLoginRespDTO userLogin(UserLoginRequestDTO requestParam, HttpServletRequest request) {
        //加密
        String encryptPassword = getEncryptPassword(requestParam.getUserPassword());
        // 查询用户账号是否存在
        LambdaQueryWrapper<User> accountQueryWrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUserAccount, requestParam.getUserAccount());
        User user = baseMapper.selectOne(accountQueryWrapper);

        if (user == null) {
            // 如果没有找到对应的用户账号，则抛出账号不存在的异常
            throw new BusinessException("账号不存在");
        } else {
            // 用户账号存在，接下来验证密码是否正确
            if (!encryptPassword.equals(user.getUserPassword())) {
                // 如果密码不匹配，则抛出密码错误的异常
                throw new BusinessException("密码错误");
            }
        }

        //记录用户登录状态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        return getLoginUserVO(user);
    }

    @Override
    public UserLoginRespDTO getLoginUser(HttpServletRequest request) {
        //判断是否登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (userObj == null) {
            throw new BusinessException(BaseErrorCode.NOT_LOGIN_ERROR);
        }
        return getLoginUserVO((User) userObj);
    }

    @Override
    public boolean userLogout(HttpServletRequest request) {
        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (userObj == null) {
            throw new BusinessException(BaseErrorCode.OPERATION_ERROR, "未登录");
        }
        // 移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    @Override
    public Long addUser(UserAddRequestDTO requestParam) {

        User user = new User();
        BeanUtils.copyProperties(requestParam, user);
        // 默认密码 12345678
        String encryptPassword = getEncryptPassword(DEFAULT_PASSWORD);
        user.setUserPassword(encryptPassword);
        boolean result = this.save(user);
        ThrowUtils.throwIf(!result, BaseErrorCode.OPERATION_ERROR);
        return user.getId();
    }

    @Override
    public UserRespDTO getUserById(Long id) {
        ThrowUtils.throwIf(id <= 0, BaseErrorCode.PARAMS_ERROR);
        User user = this.getById(id);
        ThrowUtils.throwIf(user == null, BaseErrorCode.NOT_FOUND_ERROR);
        return getUserVO(user);
    }

    @Override
    public Boolean deleteUser(DeleteRequest requestParam) {
        if (requestParam == null || requestParam.getId() <= 0) {
            throw new BusinessException(BaseErrorCode.PARAMS_ERROR);
        }
        return this.removeById(requestParam.getId());
    }

    @Override
    public boolean updateUser(UserUpdateRequestDTO requestParam) {
        if (requestParam.getId() == null) {
            throw new BusinessException(BaseErrorCode.PARAMS_ERROR);
        }
        User user = new User();
        BeanUtils.copyProperties(requestParam, user);
        boolean result = this.updateById(user);
        ThrowUtils.throwIf(!result, BaseErrorCode.OPERATION_ERROR);
        return true;
    }

    @Override
    public Page<UserRespDTO> listUserByPage(UserQueryRequestDTO requestParam) {
        ThrowUtils.throwIf(requestParam == null, BaseErrorCode.PARAMS_ERROR);
        long current = requestParam.getCurrent();
        long pageSize = requestParam.getPageSize();
        Page<User> userPage = this.page(new Page<>(current, pageSize),
                this.getQueryWrapper(requestParam));
        Page<UserRespDTO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserRespDTO> userVOList = this.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        return userVOPage;
    }


    /**
     * 密码加密
     *
     * @param userPassword 用户密码
     * @return 加密后的密码
     */
    private String getEncryptPassword(String userPassword) {
        // 盐值，混淆密码
        return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
    }

    /**
     * 返回脱敏后的用户对象
     */
    private UserLoginRespDTO getLoginUserVO(User user) {
        UserLoginRespDTO userLoginRespDTO = new UserLoginRespDTO();
        BeanUtils.copyProperties(user, userLoginRespDTO);
        return userLoginRespDTO;
    }

    private QueryWrapper<User> getQueryWrapper(UserQueryRequestDTO requestParam) {
        if (requestParam == null) {
            throw new BusinessException(BaseErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        String userAccount = requestParam.getUserAccount();
        String userName = requestParam.getUserName();
        String userRole = requestParam.getUserRole();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(userRole), "userRole", userRole);
        queryWrapper.like(StrUtil.isNotBlank(userAccount), "userAccount", userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName), "userName", userName);
        return queryWrapper;
    }


    private UserRespDTO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserRespDTO userVO = new UserRespDTO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }


    private List<UserRespDTO> getUserVOList(List<User> userList) {
        if (CollUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        return userList.stream().map(this::getUserVO).collect(Collectors.toList());
    }

}




